home *** CD-ROM | disk | FTP | other *** search
- ////////////////////////////////////////////////////////////////
- // File - V3pbclib.c
- //
- // Library for 'WinDriver for V3 Semiconductor PBC family of devices.
- // The basic idea is to get a handle for the board
- // with V3PBC_Open() and use it in the rest of the program
- // when calling WD functions. Call V3PBC_Close() when done.
- //
- ////////////////////////////////////////////////////////////////
-
- #include "../../include/windrvr.h"
- #include "../../include/windrvr_int_thread.h"
- #include "pbclib.h"
- #include <stdio.h>
-
- // this string is set to an error message, if one occurs
- CHAR V3PBC_ErrorString[1024];
-
- // internal function used by V3PBC_Open()
- BOOL V3PBC_DetectCardElements(V3PBCHANDLE hV3);
-
- // internal function for setting remap base address
- void V3PBC_SetRemapBase0(V3PBCHANDLE hV3, DWORD dwLocalAddr);
-
- // internal implementation of active delay
- void V3PBC_SleepMicro(V3PBCHANDLE hV3, DWORD nMicro);
-
- // internal functions used for EEPROM read/write
- BOOL I2C_StartSlave(V3PBCHANDLE hV3, BYTE bAddr, BYTE ReadBit);
- BOOL I2C_PollAckStart(V3PBCHANDLE hV3, BYTE bAddr, BYTE ReadBit);
- BOOL I2C_Write8(V3PBCHANDLE hV3,BYTE bData);
- BYTE I2C_Read8(V3PBCHANDLE hV3);
-
- void I2C_Stop(V3PBCHANDLE hV3);
- void I2C_NoAck(V3PBCHANDLE hV3);
- void I2C_Ack(V3PBCHANDLE hV3);
- BYTE I2C_SDAIn(V3PBCHANDLE hV3);
- void I2C_SDA(V3PBCHANDLE hV3, BOOL fHigh);
- void I2C_SCL(V3PBCHANDLE hV3, BOOL fHigh);
- void I2C_Lock(V3PBCHANDLE hV3);
- void I2C_UnLock(V3PBCHANDLE hV3);
- void I2C_Delay(V3PBCHANDLE hV3);
-
-
- //////////////////////////////////////////////////////////////////////////////
- // Card Detection/Init
- //////////////////////////////////////////////////////////////////////////////
-
- DWORD V3PBC_CountCards (DWORD dwVendorID, DWORD dwDeviceID)
- {
- WD_VERSION ver;
- WD_PCI_SCAN_CARDS pciScan;
- HANDLE hWD = INVALID_HANDLE_VALUE;
-
- V3PBC_ErrorString[0] = '\0';
- hWD = WD_Open();
- // check if handle valid & version OK
- if (hWD==INVALID_HANDLE_VALUE)
- {
- sprintf( V3PBC_ErrorString, "Failed opening " WD_PROD_NAME " device\n");
- return 0;
- }
-
- BZERO(ver);
- WD_Version(hWD,&ver);
- if (ver.dwVer<WD_VER)
- {
- sprintf( V3PBC_ErrorString, "Incorrect " WD_PROD_NAME " version\n");
- WD_Close (hWD);
- return 0;
- }
-
- BZERO(pciScan);
- pciScan.searchId.dwVendorId = dwVendorID;
- pciScan.searchId.dwDeviceId = dwDeviceID;
- WD_PciScanCards (hWD, &pciScan);
- WD_Close (hWD);
- if (pciScan.dwCards==0)
- sprintf( V3PBC_ErrorString, "no cards found\n");
- return pciScan.dwCards;
- }
-
-
- BOOL V3PBC_Open (V3PBCHANDLE *phV3, DWORD dwVendorID, DWORD dwDeviceID, DWORD nCardNum, DWORD dwOptions)
- {
- V3PBCHANDLE hV3 = (V3PBCHANDLE) malloc (sizeof (V3PBC_STRUCT));
-
- WD_VERSION ver;
- WD_PCI_SCAN_CARDS pciScan;
- WD_PCI_CARD_INFO pciCardInfo;
-
- *phV3 = NULL;
- V3PBC_ErrorString[0] = '\0';
- BZERO(*hV3);
-
- hV3->cardReg.hCard = 0;
- hV3->hWD = WD_Open();
-
- // check if handle valid & version OK
- if (hV3->hWD==INVALID_HANDLE_VALUE)
- {
- sprintf( V3PBC_ErrorString, "Failed opening " WD_PROD_NAME " device\n");
- goto Exit;
- }
-
- BZERO(ver);
- WD_Version(hV3->hWD,&ver);
- if (ver.dwVer<WD_VER)
- {
- sprintf( V3PBC_ErrorString, "Incorrect " WD_PROD_NAME " version\n");
- goto Exit;
- }
-
- pciScan.searchId.dwVendorId = dwVendorID;
- pciScan.searchId.dwDeviceId = dwDeviceID;
- WD_PciScanCards (hV3->hWD, &pciScan);
- if (pciScan.dwCards==0) // Found at least one card
- {
- sprintf( V3PBC_ErrorString, "Could not find PCI card\n");
- goto Exit;
- }
- if (pciScan.dwCards<=nCardNum)
- {
- sprintf( V3PBC_ErrorString, "Card out of range of available cards\n");
- goto Exit;
- }
-
- BZERO(pciCardInfo);
- pciCardInfo.pciSlot = pciScan.cardSlot[nCardNum];
- WD_PciGetCardInfo (hV3->hWD, &pciCardInfo);
- hV3->pciSlot = pciCardInfo.pciSlot;
- hV3->cardReg.Card = pciCardInfo.Card;
-
- hV3->fUseInt = (dwOptions & V3PBC_OPEN_USE_INT) ? TRUE : FALSE;
- if (!hV3->fUseInt)
- {
- DWORD i;
- // Remove interrupt item if not needed
- for (i=0; i<hV3->cardReg.Card.dwItems; i++)
- {
- WD_ITEMS *pItem = &hV3->cardReg.Card.Item[i];
- if (pItem->item==ITEM_INTERRUPT)
- pItem->item = ITEM_NONE;
- }
- }
- else
- {
- DWORD i;
- // make interrupt resource sharable
- for (i=0; i<hV3->cardReg.Card.dwItems; i++)
- {
- WD_ITEMS *pItem = &hV3->cardReg.Card.Item[i];
- if (pItem->item==ITEM_INTERRUPT)
- pItem->fNotSharable = FALSE;
- }
- }
-
- hV3->cardReg.fCheckLockOnly = FALSE;
- WD_CardRegister (hV3->hWD, &hV3->cardReg);
- if (hV3->cardReg.hCard==0)
- {
- sprintf ( V3PBC_ErrorString, "Failed locking device\n");
- goto Exit;
- }
-
- if (!V3PBC_DetectCardElements(hV3))
- {
- sprintf ( V3PBC_ErrorString, "Card does not have all items expected for V3 PBC\n");
- goto Exit;
- }
-
- hV3->dwReg_PCI_MAP0 = V3PBC_ReadRegDWord (hV3, V3PBC_PCI_MAP0);
-
- // Open finished OK
- *phV3 = hV3;
- return TRUE;
-
- Exit:
- // Error durin Open
- if (hV3->cardReg.hCard)
- WD_CardUnregister(hV3->hWD, &hV3->cardReg);
- if (hV3->hWD!=INVALID_HANDLE_VALUE)
- WD_Close(hV3->hWD);
- free (hV3);
- return FALSE;
- }
-
- DWORD V3PBC_ReadPCIReg(V3PBCHANDLE hV3, DWORD dwReg)
- {
- WD_PCI_CONFIG_DUMP pciCnf;
- DWORD dwVal;
-
- BZERO(pciCnf);
- pciCnf.pciSlot = hV3->pciSlot;
- pciCnf.pBuffer = &dwVal;
- pciCnf.dwOffset = dwReg;
- pciCnf.dwBytes = 4;
- pciCnf.fIsRead = TRUE;
- WD_PciConfigDump(hV3->hWD,&pciCnf);
- return dwVal;
- }
-
- void V3PBC_WritePCIReg(V3PBCHANDLE hV3, DWORD dwReg, DWORD dwData)
- {
- WD_PCI_CONFIG_DUMP pciCnf;
-
- BZERO (pciCnf);
- pciCnf.pciSlot = hV3->pciSlot;
- pciCnf.pBuffer = &dwData;
- pciCnf.dwOffset = dwReg;
- pciCnf.dwBytes = 4;
- pciCnf.fIsRead = FALSE;
- WD_PciConfigDump(hV3->hWD,&pciCnf);
- }
-
- BOOL V3PBC_DetectCardElements(V3PBCHANDLE hV3)
- {
- DWORD i;
- DWORD ad_sp;
- DWORD RegisterMask;
-
- memset (&hV3->Int, 0, sizeof (hV3->Int));
- memset (hV3->addrDesc, 0, sizeof (hV3->addrDesc));
-
- for (i=0; i<hV3->cardReg.Card.dwItems; i++)
- {
- WD_ITEMS *pItem = &hV3->cardReg.Card.Item[i];
-
- switch (pItem->item)
- {
- case ITEM_MEMORY:
- case ITEM_IO:
- {
- DWORD dwBytes;
- DWORD dwAddr;
- DWORD dwAddrDirect = 0;
- DWORD dwPhysAddr;
- BOOL fIsMemory;
- if (pItem->item==ITEM_MEMORY)
- {
- dwBytes = pItem->I.Mem.dwBytes;
- dwAddr = pItem->I.Mem.dwTransAddr;
- dwAddrDirect = pItem->I.Mem.dwUserDirectAddr;
- dwPhysAddr = pItem->I.Mem.dwPhysicalAddr;
- fIsMemory = TRUE;
- }
- else
- {
- dwBytes = pItem->I.IO.dwBytes;
- dwAddr = pItem->I.IO.dwAddr;
- dwPhysAddr = dwAddr & 0xffff;
- fIsMemory = FALSE;
- }
-
- for (ad_sp=V3PBC_ADDR_IO_BASE; ad_sp<=V3PBC_ADDR_ROM; ad_sp++)
- {
- DWORD dwPCIAddr;
- DWORD dwPCIReg;
- DWORD dwApertureSize;
-
- if (hV3->addrDesc[ad_sp].dwAddr) continue;
- if (ad_sp==V3PBC_ADDR_IO_BASE) dwPCIReg = V3PBC_PCI_IO_BASE;
- else if (ad_sp==V3PBC_ADDR_BASE0) dwPCIReg = V3PBC_PCI_BASE0;
- else if (ad_sp==V3PBC_ADDR_BASE1) dwPCIReg = V3PBC_PCI_BASE1;
- else if (ad_sp==V3PBC_ADDR_ROM) dwPCIReg = V3PBC_PCI_ROM;
- else continue;
-
- dwPCIAddr = V3PBC_ReadPCIReg(hV3, dwPCIReg);
- if (ad_sp==V3PBC_ADDR_IO_BASE)
- {
- //
- // The V3PBC_PCI_IO_BASE register uses address lines 31-8 for decoding.
- //
- RegisterMask = (DWORD) 0xffffff00;
- }
- else
- {
- dwApertureSize = (dwPCIAddr & 0x000000f0) >> 4;
- if (dwPCIAddr & 1)
- {
- //
- // The aperture defines an I/O region
- // Valid I/O values are from 4 to 7 use address lines 31-8
- //
- dwApertureSize -= 4;
- RegisterMask = (DWORD) 0xffffff00;
- }
- else
- {
- //
- // The aperture defines a memory region use address lines 31-20
- //
- RegisterMask = (DWORD) 0xfff00000;
- }
-
- //
- // Reduce mask size base on aperture size
- //
- while(dwApertureSize != 0)
- {
- RegisterMask <<=1;
- dwApertureSize--;
- }
- }
-
-
- if (dwPCIAddr & 1)
- {
- if (fIsMemory) continue;
- dwPCIAddr &= RegisterMask;
- }
- else
- {
- if (!fIsMemory) continue;
- dwPCIAddr &= RegisterMask;
- }
- //
- // Found Item description that matches PBC aperture settings, so break for loop
- //
- if (dwPCIAddr==dwPhysAddr)
- break;
- }
- if (ad_sp<=V3PBC_ADDR_ROM)
- {
- DWORD j;
- hV3->addrDesc[ad_sp].dwBytes = dwBytes;
- hV3->addrDesc[ad_sp].dwAddr = dwAddr;
- hV3->addrDesc[ad_sp].dwAddrDirect = dwAddrDirect;
- hV3->addrDesc[ad_sp].fIsMemory = fIsMemory;
- hV3->addrDesc[ad_sp].dwMask = 0;
- for (j=1; j<hV3->addrDesc[ad_sp].dwBytes && j!=0x80000000; j *= 2)
- {
- hV3->addrDesc[ad_sp].dwMask =
- (hV3->addrDesc[ad_sp].dwMask << 1) | 1;
- }
- }
- }
- break;
- case ITEM_INTERRUPT:
- if (hV3->Int.Int.hInterrupt) return FALSE;
- hV3->Int.Int.hInterrupt = pItem->I.Int.hInterrupt;
- break;
- }
- }
-
- // check that all the items needed were found
- // check if interrupt found
- if (hV3->fUseInt && !hV3->Int.Int.hInterrupt)
- {
- return FALSE;
- }
-
- // check that the registers space was found
- if (!V3PBC_IsAddrSpaceActive(hV3, V3PBC_ADDR_IO_BASE)
- || hV3->addrDesc[V3PBC_ADDR_IO_BASE].dwBytes!=V3PBC_RANGE_REG)
- return FALSE;
-
- // check that at least one memory space was found
- for (i = V3PBC_ADDR_IO_BASE; i<=V3PBC_ADDR_ROM; i++)
- if (V3PBC_IsAddrSpaceActive(hV3, i)) break;
- if (i>V3PBC_ADDR_ROM) return FALSE;
-
- return TRUE;
- }
-
- void V3PBC_Close(V3PBCHANDLE hV3)
- {
- // disable interrupts
- if (V3PBC_IntIsEnabled(hV3))
- V3PBC_IntDisable(hV3);
-
- // unregister card
- if (hV3->cardReg.hCard)
- WD_CardUnregister(hV3->hWD, &hV3->cardReg);
-
- // close WinDriver
- WD_Close(hV3->hWD);
-
- free (hV3);
- }
-
- BOOL V3PBC_IsAddrSpaceActive(V3PBCHANDLE hV3, V3PBC_ADDR addrSpace)
- {
- return hV3->addrDesc[addrSpace].dwAddr!=0;
- }
-
- DWORD V3PBC_GetRevision(V3PBCHANDLE hV3)
- {
- DWORD dwRev = V3PBC_ReadRegDWord(hV3, V3PBC_PCI_CC_REV);
- return dwRev & 0xf;
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // Access Registers range
- //////////////////////////////////////////////////////////////////////////////
-
- void V3PBC_WriteRegDWord (V3PBCHANDLE hV3, DWORD dwReg, DWORD dwData)
- {
- V3PBC_WriteSpaceDWord (hV3, V3PBC_ADDR_IO_BASE, dwReg, dwData);
- }
-
- DWORD V3PBC_ReadRegDWord (V3PBCHANDLE hV3, DWORD dwReg)
- {
- return V3PBC_ReadSpaceDWord(hV3, V3PBC_ADDR_IO_BASE, dwReg);
- }
-
- void V3PBC_WriteRegWord (V3PBCHANDLE hV3, DWORD dwReg, WORD wData)
- {
- V3PBC_WriteSpaceWord (hV3, V3PBC_ADDR_IO_BASE, dwReg, wData);
- }
-
- WORD V3PBC_ReadRegWord (V3PBCHANDLE hV3, DWORD dwReg)
- {
- return V3PBC_ReadSpaceWord(hV3, V3PBC_ADDR_IO_BASE, dwReg);
- }
-
- void V3PBC_WriteRegByte (V3PBCHANDLE hV3, DWORD dwReg, BYTE bData)
- {
- V3PBC_WriteSpaceByte (hV3, V3PBC_ADDR_IO_BASE, dwReg, bData);
- }
-
- BYTE V3PBC_ReadRegByte (V3PBCHANDLE hV3, DWORD dwReg)
- {
- return V3PBC_ReadSpaceByte(hV3, V3PBC_ADDR_IO_BASE, dwReg);
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // Access Local range
- //////////////////////////////////////////////////////////////////////////////
-
- void V3PBC_SetRemapBase0(V3PBCHANDLE hV3, DWORD dwLocalAddr)
- {
- DWORD dwMapRegValue = hV3->dwReg_PCI_MAP0;
- dwMapRegValue |= (~hV3->addrDesc[V3PBC_ADDR_BASE0].dwMask) & dwLocalAddr;
- V3PBC_WriteRegDWord( hV3, V3PBC_PCI_MAP0, dwMapRegValue);
- }
-
- void V3PBC_WriteDWord (V3PBCHANDLE hV3, DWORD dwLocalAddr, DWORD dwData)
- {
- V3PBC_SetRemapBase0(hV3, dwLocalAddr);
- V3PBC_WriteSpaceDWord (hV3, V3PBC_ADDR_BASE0,
- hV3->addrDesc[V3PBC_ADDR_BASE0].dwMask & dwLocalAddr, dwData);
- }
-
- DWORD V3PBC_ReadDWord (V3PBCHANDLE hV3, DWORD dwLocalAddr)
- {
- V3PBC_SetRemapBase0(hV3, dwLocalAddr);
- return V3PBC_ReadSpaceDWord(hV3, V3PBC_ADDR_BASE0,
- hV3->addrDesc[V3PBC_ADDR_BASE0].dwMask & dwLocalAddr);
- }
-
- void V3PBC_WriteWord (V3PBCHANDLE hV3, DWORD dwLocalAddr, WORD wData)
- {
- V3PBC_SetRemapBase0(hV3, dwLocalAddr);
- V3PBC_WriteSpaceWord (hV3, V3PBC_ADDR_BASE0,
- hV3->addrDesc[V3PBC_ADDR_BASE0].dwMask & dwLocalAddr, wData);
- }
-
- WORD V3PBC_ReadWord (V3PBCHANDLE hV3, DWORD dwLocalAddr)
- {
- V3PBC_SetRemapBase0(hV3, dwLocalAddr);
- return V3PBC_ReadSpaceWord(hV3, V3PBC_ADDR_BASE0,
- hV3->addrDesc[V3PBC_ADDR_BASE0].dwMask & dwLocalAddr);
- }
-
- void V3PBC_WriteByte (V3PBCHANDLE hV3, DWORD dwLocalAddr, BYTE bData)
- {
- V3PBC_SetRemapBase0(hV3, dwLocalAddr);
- V3PBC_WriteSpaceByte (hV3, V3PBC_ADDR_BASE0,
- hV3->addrDesc[V3PBC_ADDR_BASE0].dwMask & dwLocalAddr, bData);
- }
-
- BYTE V3PBC_ReadByte (V3PBCHANDLE hV3, DWORD dwLocalAddr)
- {
- V3PBC_SetRemapBase0(hV3, dwLocalAddr);
- return V3PBC_ReadSpaceByte(hV3, V3PBC_ADDR_BASE0,
- hV3->addrDesc[V3PBC_ADDR_BASE0].dwMask & dwLocalAddr);
- }
-
- void V3PBC_ReadBlock (V3PBCHANDLE hV3, DWORD dwLocalAddr, PVOID buf, DWORD dwBytes)
- {
- V3PBC_SetRemapBase0(hV3, dwLocalAddr);
- V3PBC_ReadSpaceBlock(hV3, hV3->addrDesc[V3PBC_ADDR_BASE0].dwMask & dwLocalAddr,
- buf, dwBytes, V3PBC_ADDR_BASE0);
- }
-
- void V3PBC_WriteBlock (V3PBCHANDLE hV3, DWORD dwLocalAddr, PVOID buf, DWORD dwBytes)
- {
- V3PBC_SetRemapBase0(hV3, dwLocalAddr);
- V3PBC_WriteSpaceBlock(hV3, hV3->addrDesc[V3PBC_ADDR_BASE0].dwMask & dwLocalAddr,
- buf, dwBytes, V3PBC_ADDR_BASE0);
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // Access Address space (low-level functions)
- //////////////////////////////////////////////////////////////////////////////
-
- // Note: addrSpace is a base address register
- BYTE V3PBC_ReadSpaceByte (V3PBCHANDLE hV3, V3PBC_ADDR addrSpace, DWORD dwOffset)
- {
- if (hV3->addrDesc[addrSpace].fIsMemory)
- {
- DWORD dwAddr = hV3->addrDesc[addrSpace].dwAddrDirect +
- (hV3->addrDesc[addrSpace].dwMask & dwOffset);
- BYTE *pByte = (BYTE *) dwAddr;
- return *pByte;
- }
- else
- {
- DWORD dwAddr = hV3->addrDesc[addrSpace].dwAddr +
- (hV3->addrDesc[addrSpace].dwMask & dwOffset);
- WD_TRANSFER trans;
- BZERO(trans);
- trans.cmdTrans = RP_BYTE;
- trans.dwPort = dwAddr;
- WD_Transfer (hV3->hWD, &trans);
- return trans.Data.Byte;
- }
- }
-
- void V3PBC_WriteSpaceByte (V3PBCHANDLE hV3, V3PBC_ADDR addrSpace, DWORD dwOffset, BYTE data)
- {
- if (hV3->addrDesc[addrSpace].fIsMemory)
- {
- DWORD dwAddr = hV3->addrDesc[addrSpace].dwAddrDirect +
- (hV3->addrDesc[addrSpace].dwMask & dwOffset);
- BYTE *pByte = (BYTE *) dwAddr;
- *pByte = data;
- }
- else
- {
- DWORD dwAddr = hV3->addrDesc[addrSpace].dwAddr +
- (hV3->addrDesc[addrSpace].dwMask & dwOffset);
- WD_TRANSFER trans;
- BZERO(trans);
- trans.cmdTrans = WP_BYTE;
- trans.dwPort = dwAddr;
- trans.Data.Byte = data;
- WD_Transfer (hV3->hWD, &trans);
- }
- }
-
- WORD V3PBC_ReadSpaceWord (V3PBCHANDLE hV3, V3PBC_ADDR addrSpace, DWORD dwOffset)
- {
- if (hV3->addrDesc[addrSpace].fIsMemory)
- {
- DWORD dwAddr = hV3->addrDesc[addrSpace].dwAddrDirect +
- (hV3->addrDesc[addrSpace].dwMask & dwOffset);
- WORD *pWord = (WORD *) dwAddr;
- return *pWord;
- }
- else
- {
- DWORD dwAddr = hV3->addrDesc[addrSpace].dwAddr +
- (hV3->addrDesc[addrSpace].dwMask & dwOffset);
- WD_TRANSFER trans;
- BZERO(trans);
- trans.cmdTrans = RP_WORD;
- trans.dwPort = dwAddr;
- WD_Transfer (hV3->hWD, &trans);
- return trans.Data.Word;
- }
- }
-
- void V3PBC_WriteSpaceWord (V3PBCHANDLE hV3, V3PBC_ADDR addrSpace, DWORD dwOffset, WORD data)
- {
- if (hV3->addrDesc[addrSpace].fIsMemory)
- {
- DWORD dwAddr = hV3->addrDesc[addrSpace].dwAddrDirect +
- (hV3->addrDesc[addrSpace].dwMask & dwOffset);
- WORD *pWord = (WORD *) dwAddr;
- *pWord = data;
- }
- else
- {
- DWORD dwAddr = hV3->addrDesc[addrSpace].dwAddr +
- (hV3->addrDesc[addrSpace].dwMask & dwOffset);
- WD_TRANSFER trans;
- BZERO(trans);
- trans.cmdTrans = WP_WORD;
- trans.dwPort = dwAddr;
- trans.Data.Word = data;
- WD_Transfer (hV3->hWD, &trans);
- }
- }
-
- DWORD V3PBC_ReadSpaceDWord (V3PBCHANDLE hV3, V3PBC_ADDR addrSpace, DWORD dwOffset)
- {
- if (hV3->addrDesc[addrSpace].fIsMemory)
- {
- DWORD dwAddr = hV3->addrDesc[addrSpace].dwAddrDirect +
- (hV3->addrDesc[addrSpace].dwMask & dwOffset);
- DWORD *pDword = (DWORD *) dwAddr;
- return *pDword;
- }
- else
- {
- DWORD dwAddr = hV3->addrDesc[addrSpace].dwAddr +
- (hV3->addrDesc[addrSpace].dwMask & dwOffset);
- WD_TRANSFER trans;
- BZERO(trans);
- trans.cmdTrans = RP_DWORD;
- trans.dwPort = dwAddr;
- WD_Transfer (hV3->hWD, &trans);
- return trans.Data.Dword;
- }
- }
-
- void V3PBC_WriteSpaceDWord (V3PBCHANDLE hV3, V3PBC_ADDR addrSpace, DWORD dwOffset, DWORD data)
- {
- if (hV3->addrDesc[addrSpace].fIsMemory)
- {
- DWORD dwAddr = hV3->addrDesc[addrSpace].dwAddrDirect +
- (hV3->addrDesc[addrSpace].dwMask & dwOffset);
- DWORD *pDword = (DWORD *) dwAddr;
- *pDword = data;
- }
- else
- {
- DWORD dwAddr = hV3->addrDesc[addrSpace].dwAddr +
- (hV3->addrDesc[addrSpace].dwMask & dwOffset);
- WD_TRANSFER trans;
- BZERO(trans);
- trans.cmdTrans = WP_DWORD;
- trans.dwPort = dwAddr;
- trans.Data.Dword = data;
- WD_Transfer (hV3->hWD, &trans);
- }
- }
-
- void V3PBC_ReadWriteSpaceBlock (V3PBCHANDLE hV3, DWORD dwOffset, PVOID buf,
- DWORD dwBytes, BOOL fIsRead, V3PBC_ADDR addrSpace, V3PBC_MODE mode)
- {
- WD_TRANSFER trans;
- DWORD dwAddr = hV3->addrDesc[addrSpace].dwAddr +
- (hV3->addrDesc[addrSpace].dwMask & dwOffset);
-
- BZERO(trans);
-
- if (hV3->addrDesc[addrSpace].fIsMemory)
- {
- if (fIsRead)
- {
- if (mode==V3PBC_MODE_BYTE) trans.cmdTrans = RM_SBYTE;
- else if (mode==V3PBC_MODE_WORD) trans.cmdTrans = RM_SWORD;
- else trans.cmdTrans = RM_SDWORD;
- }
- else
- {
- if (mode==V3PBC_MODE_BYTE) trans.cmdTrans = WM_SBYTE;
- else if (mode==V3PBC_MODE_WORD) trans.cmdTrans = WM_SWORD;
- else trans.cmdTrans = WM_SDWORD;
- }
- }
- else
- {
- if (fIsRead)
- {
- if (mode==V3PBC_MODE_BYTE) trans.cmdTrans = RP_SBYTE;
- else if (mode==V3PBC_MODE_WORD) trans.cmdTrans = RP_SWORD;
- else trans.cmdTrans = RP_SDWORD;
- }
- else
- {
- if (mode==V3PBC_MODE_BYTE) trans.cmdTrans = WP_SBYTE;
- else if (mode==V3PBC_MODE_WORD) trans.cmdTrans = WP_SWORD;
- else trans.cmdTrans = WP_SDWORD;
- }
- }
- trans.dwPort = dwAddr;
- trans.fAutoinc = TRUE;
- trans.dwBytes = dwBytes;
- trans.dwOptions = 0;
- trans.Data.pBuffer = buf;
- WD_Transfer (hV3->hWD, &trans);
- }
-
- void V3PBC_ReadSpaceBlock (V3PBCHANDLE hV3, DWORD dwOffset, PVOID buf,
- DWORD dwBytes, V3PBC_ADDR addrSpace)
- {
- V3PBC_ReadWriteSpaceBlock (hV3, dwOffset, buf, dwBytes, TRUE, addrSpace, V3PBC_MODE_DWORD);
- }
-
- void V3PBC_WriteSpaceBlock (V3PBCHANDLE hV3, DWORD dwOffset, PVOID buf,
- DWORD dwBytes, V3PBC_ADDR addrSpace)
- {
- V3PBC_ReadWriteSpaceBlock (hV3, dwOffset, buf, dwBytes, FALSE, addrSpace, V3PBC_MODE_DWORD);
- }
-
-
- //////////////////////////////////////////////////////////////////////////////
- // Interrupts
- //////////////////////////////////////////////////////////////////////////////
-
- BOOL V3PBC_IntIsEnabled (V3PBCHANDLE hV3)
- {
- if (!hV3->fUseInt) return FALSE;
- if (!hV3->Int.hThread) return FALSE;
- return TRUE;
- }
-
- VOID V3PBC_IntHandler (PVOID pData)
- {
- V3PBCHANDLE hV3 = (V3PBCHANDLE) pData;
- V3PBC_INT_RESULT intResult;
-
- intResult.dwCounter = hV3->Int.Int.dwCounter;
- intResult.dwLost = hV3->Int.Int.dwLost;
- intResult.fStopped = hV3->Int.Int.fStopped;
- intResult.dwStatusReg = hV3->Int.Trans[0].Data.Dword;
- hV3->Int.funcIntHandler(hV3, &intResult);
- }
-
- BOOL V3PBC_IntEnable (V3PBCHANDLE hV3, V3PBC_INT_HANDLER funcIntHandler)
- {
- DWORD dwIntStatus;
- DWORD dwAddr;
-
- if (!hV3->fUseInt) return FALSE;
- // check if interrupt is already enabled
- if (hV3->Int.hThread) return FALSE;
-
- dwIntStatus = V3PBC_ReadRegDWord (hV3, V3PBC_PCI_BPARM);
-
- BZERO(hV3->Int.Trans);
- // This is a samlpe of handling interrupts:
- // Two transfer commands are issued. First the value of the interrrupt control/status
- // register is read. Then, a value of ZERO is written.
- // This will cancel interrupts after the first interrupt occurs.
- // When using interrupts, this section will have to change:
- // you must put transfer commands to CANCEL the source of the interrupt, otherwise, the
- // PC will hang when an interrupt occurs!
- dwAddr = hV3->addrDesc[V3PBC_ADDR_IO_BASE].dwAddr + V3PBC_PCI_BPARM;
- hV3->Int.Trans[0].cmdTrans = hV3->addrDesc[V3PBC_ADDR_IO_BASE].fIsMemory ? RM_DWORD : RP_DWORD;
- hV3->Int.Trans[0].dwPort = dwAddr;
- hV3->Int.Trans[1].cmdTrans = hV3->addrDesc[V3PBC_ADDR_IO_BASE].fIsMemory ? WM_DWORD : WP_DWORD;
- hV3->Int.Trans[1].dwPort = dwAddr;
- hV3->Int.Trans[1].Data.Dword = dwIntStatus & ~BIT8; // put here the data to write to the control register
- hV3->Int.Int.dwCmds = 2;
- hV3->Int.Int.Cmd = hV3->Int.Trans;
- hV3->Int.Int.dwOptions |= INTERRUPT_CMD_COPY;
-
- // this calls WD_IntEnable() and creates an interrupt handler thread
- hV3->Int.funcIntHandler = funcIntHandler;
- if (!InterruptThreadEnable(&hV3->Int.hThread, hV3->hWD, &hV3->Int.Int, V3PBC_IntHandler, (PVOID) hV3))
- return FALSE;
-
- // this enables interrupts
- // Enable INTA to interrupt the PCI bus
- V3PBC_WriteRegDWord (hV3, V3PBC_PCI_BPARM, dwIntStatus | BIT8);
-
- return TRUE;
- }
-
- void V3PBC_IntDisable (V3PBCHANDLE hV3)
- {
- DWORD dwIntStatus;
-
- if (!hV3->fUseInt) return;
- if (!hV3->Int.hThread) return;
-
- // this disables interrupts
- // Disable interrupt assumes INTA was enabled
- dwIntStatus = V3PBC_ReadRegDWord (hV3, V3PBC_PCI_BPARM);
- V3PBC_WriteRegDWord (hV3, V3PBC_PCI_BPARM, dwIntStatus & ~BIT8);
-
- // this calls WD_IntDisable()
- InterruptThreadDisable(hV3->Int.hThread);
-
- hV3->Int.hThread = NULL;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////
- // DMA
- //////////////////////////////////////////////////////////////////////////////
-
- BOOL V3PBC_DMAOpen(V3PBCHANDLE hV3, WD_DMA *pDMA, DWORD dwBytes)
- {
- V3PBC_ErrorString[0] = '\0';
- BZERO(*pDMA);
- pDMA->pUserAddr = NULL; // the kernel will allocate the buffer
- pDMA->dwBytes = dwBytes; // size of buffer to allocate
- pDMA->dwOptions = DMA_KERNEL_BUFFER_ALLOC;
- WD_DMALock (hV3->hWD, pDMA);
- if (!pDMA->hDma)
- {
- sprintf (V3PBC_ErrorString, "Failed allocating the buffer!\n");
- return FALSE;
- }
-
- return TRUE;
- }
-
- void V3PBC_DMAClose(V3PBCHANDLE hV3, WD_DMA *pDMA)
- {
- WD_DMAUnlock (hV3->hWD, pDMA);
- }
-
- BOOL V3PBC_DMAStart(V3PBCHANDLE hV3, V3_DMA_CHANNEL dmaChannel, WD_DMA *pDMA, BOOL fRead,
- BOOL fBlocking, DWORD dwBytes, DWORD dwOffset, DWORD dwLocalAddr)
- {
- DWORD dwDMACSR0;
- DWORD dwChannelOffset = dmaChannel*0x10;
-
- V3PBC_WriteRegDWord(hV3, V3PBC_DMA_LOCAL_ADDR0 + dwChannelOffset, dwLocalAddr);
- V3PBC_WriteRegDWord(hV3, V3PBC_DMA_PCI_ADDR0 + dwChannelOffset,
- (DWORD) pDMA->Page[0].pPhysicalAddr + dwOffset);
- // BIT[0-23] count is in DWORDS divide by 4
- // BIT24 - initiate transfer (write)
- // BIT24 - DMA transfer busy (read)
- // BIT28 - transfer direction
- // Preserve chain, priority and byte swapping
- dwDMACSR0 = V3PBC_ReadRegDWord(hV3, V3PBC_DMA_LENGTH0 + dwChannelOffset) & 0xac00000;
- V3PBC_WriteRegDWord(hV3, V3PBC_DMA_LENGTH0 + dwChannelOffset, (fRead ? 0 : BIT28) | BIT24 | dwBytes >> 2 | dwDMACSR0);
- // if blocking then check BIT24 to wait for transfer to complete
- if (fBlocking)
- while (!V3PBC_DMAIsDone(hV3, dmaChannel));
-
- return TRUE;
- }
-
- BOOL V3PBC_DMAIsDone(V3PBCHANDLE hV3, V3_DMA_CHANNEL dmaChannel)
- {
- if (V3PBC_ReadRegDWord(hV3, V3PBC_DMA_LENGTH0 + dmaChannel*0x10) & BIT24)
- return FALSE;
- return TRUE;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////
- // Card Reset
- //////////////////////////////////////////////////////////////////////////////
-
- void V3PBC_PulseLocalReset(V3PBCHANDLE hV3, WORD wDelay)
- {
- WORD System;
-
- // Unlock the system register
- V3PBC_WriteRegWord(hV3, V3PBC_SYSTEM, SYSTEM_UNLOCK_TOKEN);
-
- // Assert the local reset line
- System = V3PBC_ReadRegWord(hV3, V3PBC_SYSTEM);
- V3PBC_WriteRegWord((V3PBCHANDLE) hV3, V3PBC_SYSTEM, (WORD) (System & ~SYSTEM_RST_OUT));
-
- // Lock the system register
- V3PBC_WriteRegWord(hV3, V3PBC_SYSTEM, (WORD) (System | SYSTEM_LOCK));
-
- // Delay
- V3PBC_SleepMicro(hV3, ((DWORD) wDelay) * 1000);
-
- // Unlock the system register
- V3PBC_WriteRegWord(hV3, V3PBC_SYSTEM, SYSTEM_UNLOCK_TOKEN);
-
- // De-assert the local reset line
- System = V3PBC_ReadRegWord(hV3, (WORD) V3PBC_SYSTEM);
- V3PBC_WriteRegWord(hV3, V3PBC_SYSTEM, (WORD) (System | SYSTEM_RST_OUT));
-
- // Lock the system register
- V3PBC_WriteRegWord(hV3, V3PBC_SYSTEM, (WORD) (System | SYSTEM_LOCK));
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // Sleep (delay)
- //////////////////////////////////////////////////////////////////////////////
-
- void V3PBC_SleepMicro(V3PBCHANDLE hV3, DWORD nMicro)
- {
- WD_SLEEP sleep;
- BZERO (sleep);
- sleep.dwMicroSeconds = nMicro;
- WD_Sleep( hV3->hWD, &sleep);
- }
-
-
- //////////////////////////////////////////////////////////////////////////////
- // EEPROM read/write
- //////////////////////////////////////////////////////////////////////////////
-
- // Note: V3PBC_EEPROMInit should be called for each board.
- // This routine will force a stop condition on the I2C bus.
- // The clock and data lines will be left high and this routine will
- // return after a half clock.
- void V3PBC_EEPROMInit(V3PBCHANDLE hV3)
- {
- // Unlock the system register
- I2C_UnLock(hV3);
-
- // Ensure that the I2C clock and data lines are in a known state
- I2C_Stop(hV3);
- I2C_Delay(hV3);
-
- // Lock the system register
- I2C_Lock(hV3);
- }
-
- // Parameters:
- // BYTE bSlaveAddr - 3 bit address of device been selected
- // BYTE bAddr - address of EEPROM location to be read from
- // BYTE bData - value to be written to EEPROM
- //
- // Return:
- // BOOL fStatus - TRUE if read successful
- //
- // Description:
- // This routine writes a byte to the slave device's address specified.
- // This routine uses the Write Byte method from the Atmel documentation.
- BOOL V3PBC_EEPROMWrite(V3PBCHANDLE hV3, BYTE bSlaveAddr, BYTE bAddr, BYTE bData)
- {
- BOOL fStatus = TRUE;
-
- // Set upper device address
- bSlaveAddr |= I2C_1010;
-
- // Unlock the system register
- I2C_UnLock(hV3);
-
- // Send device Address and wait for Ack, bAddr is sent as a write
- if (!I2C_PollAckStart(hV3, bSlaveAddr, I2C_WRITE))
- fStatus = FALSE;
- else
- {
- // Send bAddr as the address to write
- if (!I2C_Write8(hV3, bAddr))
- fStatus = FALSE;
- else
- {
- // Send the value to write
- if (!I2C_Write8(hV3, bData))
- fStatus = FALSE;
- }
- }
-
- // Clean up the bus with a stop condition
- I2C_Stop(hV3);
-
- // Lock the system register
- I2C_Lock(hV3);
- return fStatus;
- }
-
- // Parameters:
- // BYTE bSlaveAddr - 3 bit address of device been selected
- // BYTE bAddr - address of EEPROM location to be read from
- // BYTE *bData - EEPROM data read back (pointer to data passed)
- //
- // Return:
- // BOOL fStatus - TRUE if read successful
- //
- // Description:
- // This routine reads back a byte from the slave device's address
- // specificed. This routine uses the Random Read method in the Atmel
- // documentation.
- BOOL V3PBC_EEPROMRead(V3PBCHANDLE hV3, BYTE bSlaveAddr, BYTE bAddr, BYTE *bData)
- {
- BOOL fStatus = TRUE;
-
- // Set upper device address
- bSlaveAddr |= I2C_1010;
-
- // Unlock the system register
- I2C_UnLock(hV3);
-
- // Send device Address and wait for Ack, bAddr is sent as a write
- if (!I2C_PollAckStart(hV3, bSlaveAddr, I2C_WRITE))
- fStatus = FALSE;
- else
- {
- // Send bAddr as the random address to be read
- if (!I2C_Write8(hV3, bAddr))
- fStatus = FALSE;
- else
- {
- // Send a START condition and device address this time as read
- if (!I2C_StartSlave(hV3, bSlaveAddr, I2C_READ))
- fStatus = FALSE;
- else
- // read the date back from EEPROM
- *bData = I2C_Read8(hV3);
- }
- }
-
- // clean up bus with a NaK and Stop condition
- I2C_NoAck(hV3);
- I2C_Stop(hV3);
-
- // Lock the system register
- I2C_Lock(hV3);
- return fStatus;
- }
-
- // Parameters:
- // BYTE bAddr - 3 bit address of device been selected
- // bit ReadBit - Set if command is to be a read, reset if command is a write
- //
- // Return:
- // TRUE - read was successful
- // FALSE - if negative acknowledge was received
- //
- // Description:
- // All commands are preceded by the start condition, which is a high
- // to low transition of SDA when SCL is high. All I2C devices
- // continuously monitor the SDA and SCL lines for the start condition
- // and will not respond to any command until this condition has been met.
- //
- // Once a device detects that it is being addressed it outputs an
- // acknowledge on the SDA line. Depending on the state of the read/write
- // bit, the device will execute a read or write operation.
- //
- // +-----+-----+-----+-----+-----+-----+-----+-----+
- // | SA6 | SA5 | SA4 | SA3 | SA2 | SA1 | SA0 | R/W |
- // +-----+-----+-----+-----+-----+-----+-----+-----+
- // |--- 1=read, 0=write
- BOOL I2C_StartSlave(V3PBCHANDLE hV3, BYTE bAddr, BYTE ReadBit)
- {
- I2C_SCL(hV3, TRUE);
- I2C_Delay(hV3);
- I2C_SDA(hV3, FALSE);
- I2C_Delay(hV3);
- I2C_SCL(hV3, FALSE);
- I2C_Delay(hV3);
- return I2C_Write8(hV3, (BYTE) (bAddr<<1 | ReadBit));
- }
-
- // Parameters:
- // V3PBCHANDLE hV3 - Handle to PBC32 data structure.
- // BYTE bAddr - 3 bit address of device been selected
- // bit ReadBit - Set if command is to be a read, reset if command is a write
- //
- // Return:
- // FALSE - device is not responding (retried out)
- // TRUE - read was successful
- //
- // Description:
- // This routine checks the status of the device being written to by
- // issuing a start condition followed by check for ACK. If the slave
- // device is unable to communicate, the write command will not be
- // acknowledged and we should wait. This routine will try I2C_RETRY times for
- // an ACK before returning a I2C_BUSY indication.
- BOOL I2C_PollAckStart(V3PBCHANDLE hV3, BYTE bAddr, BYTE ReadBit)
- {
- BYTE bTries = I2C_RETRY;
- do
- {
- I2C_SDA(hV3, FALSE);
- I2C_Delay(hV3);
- I2C_SCL(hV3, FALSE);
- I2C_Delay(hV3);
- if (I2C_Write8(hV3, (BYTE) (bAddr<<1 | ReadBit)))
- return TRUE;
- }
- while(bTries--);
- return FALSE;
- }
-
- // Reads eight bits from the I2C bus.
- // Return: BYTE bData - returns a byte of data
- BYTE I2C_Read8(V3PBCHANDLE hV3)
- {
- BYTE i, bData=0;
-
- I2C_SDA(hV3, TRUE);
- for (i=8; i; --i )
- {
- I2C_SCL(hV3, TRUE);
- I2C_Delay(hV3);
- bData = (bData<<1) | I2C_SDAIn(hV3);
- I2C_SCL(hV3, FALSE);
- I2C_Delay(hV3);
- }
- return bData;
- }
-
- // Return:
- // TRUE - OK
- // FALSE - BUSY or negative acknowledge
- //
- // Description:
- // This routine writes out all 8 bits of data out to the I2C bus. After
- // writing out the data, the routine reads the ACK/NACK response back and
- // returns it to the caller.
- BOOL I2C_Write8(V3PBCHANDLE hV3,BYTE bData)
- {
- BYTE bAck;
- BYTE i;
- for (i=0x80; i; i >>=1 )
- {
- I2C_SDA(hV3, (i & bData) ? TRUE : FALSE);
- I2C_SCL(hV3, TRUE);
- I2C_Delay(hV3);
- I2C_SCL(hV3, FALSE);
- I2C_Delay(hV3);
- }
- I2C_SDA(hV3, TRUE);
- I2C_SCL(hV3, TRUE);
- bAck= I2C_SDAIn(hV3);
- I2C_Delay(hV3);
- I2C_SCL(hV3, FALSE);
- I2C_Delay(hV3);
-
- return bAck==0;
- }
-
- // All communications must be terminated by a stop condition which
- // is a low to high transition of SDA while SCL is high. A stop
- // condition can only be issued after the transmitting device has
- // released the bus.
- void I2C_Stop(V3PBCHANDLE hV3)
- {
- I2C_SDA(hV3, FALSE);
- I2C_Delay(hV3);
- I2C_SCL(hV3, TRUE);
- I2C_Delay(hV3);
- I2C_SDA(hV3, TRUE);
- }
-
- // The No-Acknowledge is a software convention used to indicate
- // unsucessful data transfers. The transmitting device, either
- // master or slave, will release the bus after transmitting
- // eight bits. During the ninth clock cycle the receiver will
- // pull the SDA line high to indicate that it did not received the
- // eight bits of data.
- void I2C_NoAck(V3PBCHANDLE hV3)
- {
- I2C_SDA(hV3, TRUE);
- I2C_Delay(hV3);
- I2C_SCL(hV3, TRUE);
- I2C_Delay(hV3);
- I2C_SCL(hV3, FALSE);
- }
-
- // Acknowledge is a software convention used to indicate
- // sucessful data transfers. The transmitting device, either
- // master or slave, will release the bus after transmitting
- // eight bits. During the ninth clock cycle the receiver will
- // pull the SDA line low to acknowledge that it received the
- // eight bits of data.
- void I2C_Ack(V3PBCHANDLE hV3)
- {
- I2C_SDA(hV3, FALSE);
- I2C_Delay(hV3);
- I2C_SCL(hV3, TRUE);
- I2C_Delay(hV3);
- I2C_SCL(hV3, FALSE);
- }
-
- // This routine returns the state of the Serial Data line
- // Return: BYTE bData - state of the Serial Data line
- BYTE I2C_SDAIn(V3PBCHANDLE hV3)
- {
- WORD wSystem;
-
- wSystem = V3PBC_ReadRegWord(hV3, V3PBC_SYSTEM);
- return ((wSystem & SYSTEM_SDA_IN) >> SYSTEM_SDA_IN_SHIFT);
- }
-
- // This routine sets the Serial Data line to the desired state.
- //
- // Parameters:
- // BOOL fHigh - what state the SDA is to be set to
- void I2C_SDA(V3PBCHANDLE hV3, BOOL fHigh)
- {
- WORD wSystem;
-
- wSystem = V3PBC_ReadRegWord(hV3, V3PBC_SYSTEM);
- if(fHigh)
- wSystem |= SYSTEM_SDA_OUT;
- else
- wSystem &= ~SYSTEM_SDA_OUT;
- V3PBC_WriteRegWord(hV3, V3PBC_SYSTEM, wSystem);
- }
-
- // This routine sets the Serial Clock line to the desired state.
- //
- // Parameters:
- // BOOL fHigh - what state the SCL is to be set to
- void I2C_SCL(V3PBCHANDLE hV3, BOOL fHigh)
- {
- WORD wSystem;
-
- wSystem = V3PBC_ReadRegWord(hV3, V3PBC_SYSTEM);
- if(fHigh)
- wSystem |= SYSTEM_SCL;
- else
- wSystem &= ~SYSTEM_SCL;
- V3PBC_WriteRegWord(hV3, V3PBC_SYSTEM, wSystem);
- }
-
- // This routine disables the Serial Clock pin, and sets the sytem
- // lock bit.
- void I2C_Lock(V3PBCHANDLE hV3)
- {
- WORD wSystem;
-
- wSystem = V3PBC_ReadRegWord(hV3, V3PBC_SYSTEM);
- V3PBC_WriteRegWord(hV3, V3PBC_SYSTEM, (WORD) (wSystem & ~SYSTEM_SPROM_EN));
- V3PBC_WriteRegWord(hV3, V3PBC_SYSTEM, (WORD) (wSystem | SYSTEM_LOCK));
- }
-
- // This routine enable the sytem register for writting, and enables
- // the Serial Clock output pin.
- void I2C_UnLock(V3PBCHANDLE hV3)
- {
- WORD wSystem;
-
- V3PBC_WriteRegWord(hV3, V3PBC_SYSTEM, SYSTEM_UNLOCK_TOKEN);
- wSystem = V3PBC_ReadRegWord(hV3, V3PBC_SYSTEM);
- V3PBC_WriteRegWord(hV3, V3PBC_SYSTEM, (WORD) (wSystem |SYSTEM_SPROM_EN));
- }
-
- // This routine inserts delay. 0.005 Milliseconds is enough time
- void I2C_Delay(V3PBCHANDLE hV3)
- {
- V3PBC_SleepMicro(hV3, 5);
- }
-